from hashlib import sha1
from xml.etree.ElementTree import fromstring

from django.conf import settings
from django.http import JsonResponse, HttpResponse
from django.views import View
from loguru import logger

from api.encry_method import MessageEncryptionAndDecryption
from api.message_handler import MessageHandler
from api.public_methods import response_json
from .tasks import check_user_exists


class Message(View):

    def post(self, request):
        """ 接受公众号消息 """
        try:
            post_request_data = {i.tag: i.text for i in fromstring(request.body)}
            get_request_data = {k: v for k, v in request.GET.items()}
            origin_id = post_request_data.get('ToUserName')
            assert origin_id, f'未接收到消息原始id, post_data:{post_request_data}'
            subscription_info = settings.SUBSCRIPTION_INFO.get(origin_id)
            assert subscription_info, '未获取到公众号系统参数'

            if (request_data_encrypt := post_request_data.get('Encrypt')) is not None:
                content = MessageEncryptionAndDecryption(
                    token=subscription_info['token'], encoding_aes_key=subscription_info['aes_key']
                ).decrypt(
                    msg_timestamp=get_request_data['timestamp'],
                    msg_nonce=get_request_data['nonce'],
                    msg_encrypt=request_data_encrypt,
                    msg_signature=get_request_data['msg_signature'],
                    appid=subscription_info['app_id']
                )
                assert content, '消息解析失败'
                post_request_data = {i.tag: i.text for i in fromstring(content)}

            # todo: 如果服务有获取用户信息权限，就去检查用户信息是否记录，后期迁移到celery
            subscription_info['can_get_user_info'] and check_user_exists.delay(post_request_data['FromUserName'])

            # todo: 处理消息，后期移动到celery
            reply_msg = MessageHandler(app_name=subscription_info["app_name"], **post_request_data)
            logger.info(f'Receive message from {subscription_info["app_name"]}: {post_request_data} REPLAY:{reply_msg}')
            return HttpResponse(reply_msg)
        except AssertionError as e:
            logger.error(f'{e}')
            return JsonResponse(response_json(code=1, message=f'{e}'))
        except Exception as e:
            logger.exception(f'接受公众号消息发生错误，{e}')
            return JsonResponse(response_json(code=1, message=f'接受公众号消息发生错误，{e}'))

    def get(self, request):
        try:
            signature = request.GET.get('signature')
            timestamp = request.GET.get('timestamp')
            nonce = request.GET.get('nonce')
            echostr = request.GET.get('echostr')
            for subscription_value_obj in settings.SUBSCRIPTION_INFO.values():
                logger.info(subscription_value_obj)
                signature_text = ''.join(sorted([subscription_value_obj['token'], timestamp, nonce]))
                self_signature = sha1(signature_text.encode()).hexdigest()
                if self_signature == signature:
                    return HttpResponse(echostr)
            return HttpResponse('')
        except AssertionError as e:
            return JsonResponse(response_json(code=1, message=f'{e}'))
        except Exception as e:
            logger.exception(f'验证Token失败，{e}')
            return JsonResponse(response_json(code=1, message=f'验证Token失败，{e}'))
